package mcmt.view;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;

import java.io.File;
import java.io.OutputStream;

import mcmt.controller.FileController;
import mcmt.controller.ReportController;
import mcmt.controller.XmlReportController;
import mcmt.model.ComparisonException;
import mcmt.model.Currency;
import mcmt.model.Item;
import mcmt.model.ReportItem;
import javax.swing.table.DefaultTableModel;

public class ExchangeApp {

	private JFrame mainFrame;
	private JTextField currencyValue;
	private FileController fileController;
	private List<ReportItem> items = new ArrayList<>();
	private JTable exchangeTable;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					ExchangeApp window = new ExchangeApp();
					window.mainFrame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	private static void generateHtmlReport() throws Exception {
		TransformerFactory factory = TransformerFactory.newInstance();
		Source xslt = new StreamSource(new File("toHTML.xsl"));
		Transformer transformer = factory.newTransformer(xslt);

		Source text = new StreamSource(new File("file1.xml"));
		transformer.transform(text, new StreamResult(new File("output.xhtml")));
	}

	private static void generateTxtReport() throws Exception {
		TransformerFactory factory = TransformerFactory.newInstance();
		Source xslt = new StreamSource(new File("toTxt.xsl"));
		Transformer transformer = factory.newTransformer(xslt);

		Source text = new StreamSource(new File("file1.xml"));
		transformer.transform(text, new StreamResult(new File("output.txt")));
	}

	private static void generatePdfReport() throws Exception {
		System.out.println("FOP XMLTOPDFConverter\n");
		System.out.println("Preparing...");
		// Setup input and output files

		// configure fopFactory as desired
		FopFactory fopFactory = FopFactory.newInstance();

		FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
		// configure foUserAgent as desired

		// Setup output
		OutputStream out = new java.io.FileOutputStream("output.pdf");
		out = new java.io.BufferedOutputStream(out);

		try {
			// Construct fop with desired output format
			Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent,
					out);

			// Setup XSLT
			TransformerFactory factory = TransformerFactory.newInstance();
			Transformer transformer = factory.newTransformer(new StreamSource(
					"toPdf.xsl"));

			// Set the value of a <param> in the stylesheet
			transformer.setParameter("versionParam", "2.0");

			// Setup input for XSLT transformation
			Source src = new StreamSource("file1.xml");

			// Resulting SAX events (the generated FO) must be piped through
			// to FOP
			Result res = new SAXResult(fop.getDefaultHandler());

			// Start XSLT transformation and FOP processing
			transformer.transform(src, res);
		} finally {
			out.close();
		}

		System.out.println("Success!");
	}

	/**
	 * Create the application.
	 */
	public ExchangeApp() {
		this.fileController = new FileController();
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	@SuppressWarnings("rawtypes")
	private void initialize() {
		mainFrame = new JFrame();
		mainFrame.setResizable(false);
		mainFrame.setTitle("Exchange App");
		mainFrame.setBounds(100, 100, 600, 400);
		mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		mainFrame.getContentPane().setLayout(null);

		currencyValue = new JTextField();
		currencyValue.setText("1.0");
		currencyValue.setBounds(10, 11, 86, 20);
		mainFrame.getContentPane().add(currencyValue);
		currencyValue.setColumns(10);

		final JComboBox firstCurrencyComboBox = new JComboBox();
		firstCurrencyComboBox.setModel(new DefaultComboBoxModel(Currency
				.values()));
		firstCurrencyComboBox.setBounds(106, 11, 165, 20);
		mainFrame.getContentPane().add(firstCurrencyComboBox);

		final JComboBox secondCurrencyComboBox = new JComboBox();
		secondCurrencyComboBox.setModel(new DefaultComboBoxModel(Currency
				.values()));
		secondCurrencyComboBox.setBounds(309, 11, 165, 20);
		mainFrame.getContentPane().add(secondCurrencyComboBox);

		JButton calculateButton = new JButton("Calculate");
		calculateButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				try {
					String homeCode = ((Currency) firstCurrencyComboBox
							.getSelectedItem()).getCountryCode();
					String foreignCode = ((Currency) secondCurrencyComboBox
							.getSelectedItem()).getCountryCode();

					if (homeCode.equals(foreignCode)) {
						throw new ComparisonException();
					}

					double value = Double.parseDouble(currencyValue.getText());
					fileController.setFileURL(homeCode, foreignCode, value);

					// add exchange to the report
					Double outputValue = Math.round(fileController
							.calculateResult() * 100) / 100.0;
					ReportItem item = new ReportItem();
					item.setInputCurrency((Currency) firstCurrencyComboBox
							.getSelectedItem());
					item.setOutputCurrency((Currency) secondCurrencyComboBox
							.getSelectedItem());
					item.setOutputValue(outputValue);
					item.setItem(fileController.getItem());
					items.add(item);

					// add to exchange jtable
					String exchange = fileController.getItem().getTitle();
					String desc = fileController.getItem().getDescription();
					String rate = Double.toString(fileController.getItem()
							.getRate());
					String unit = Double.toString(fileController.getItem()
							.getUnit());
					String result = Double.toString(outputValue);
					String dateStamp = fileController.getItem().getPubDate();

					DefaultTableModel model = (DefaultTableModel) exchangeTable
							.getModel();
					model.addRow(new Object[] { exchange, desc, rate, unit,
							result, dateStamp });


				} catch (NumberFormatException exp) {
					JOptionPane.showMessageDialog(mainFrame,
							"Cannot convert value!", "Error",
							JOptionPane.ERROR_MESSAGE);

				} catch (ComparisonException exp) {
					JOptionPane.showMessageDialog(mainFrame, exp.getMessage(),
							"Error", JOptionPane.ERROR_MESSAGE);
				}

			}
		});
		calculateButton.setBounds(484, 10, 100, 23);
		mainFrame.getContentPane().add(calculateButton);

		JButton txtButton = new JButton("Generate .txt report");
		txtButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				System.out.println("Action: " + items.size());
				ReportController rc = new XmlReportController();
				rc.generateReport(items);
				try {
					generateTxtReport();
				} catch (Exception ex) {

				}
			}
		});
		txtButton.setBounds(416, 42, 168, 23);
		mainFrame.getContentPane().add(txtButton);

		JButton htmlButton = new JButton("Generate .html report");
		htmlButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				System.out.println("Action: " + items.size());
				ReportController rc = new XmlReportController();
				rc.generateReport(items);
				try {
					generateHtmlReport();
				} catch (Exception ex) {

				}
			}
		});
		htmlButton.setBounds(213, 42, 168, 23);
		mainFrame.getContentPane().add(htmlButton);

		JButton pdfButton = new JButton("Generate .pdf report");
		pdfButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				System.out.println("Action: " + items.size());
				ReportController rc = new XmlReportController();
				rc.generateReport(items);
				try {
					generatePdfReport();
				} catch (Exception ex) {

				}
			}
		});
		pdfButton.setBounds(10, 42, 168, 23);
		mainFrame.getContentPane().add(pdfButton);

		JLabel arrowLabel = new JLabel("=>");
		arrowLabel.setBounds(281, 14, 46, 14);
		mainFrame.getContentPane().add(arrowLabel);

		exchangeTable = new JTable();
		exchangeTable.setModel(new DefaultTableModel(new Object[][] {},
				new String[] { "Exchange", "Description", "Rate", "Unit",
						"Result", "Date Stamp" }));
		exchangeTable.setBounds(10, 76, 574, 285);
		
		/*
		exchangeTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
		exchangeTable.getColumnModel().getColumn(0).setPreferredWidth(27);
		//exchangeTable.getColumnModel().getColumn(1).setPreferredWidth(120);
		exchangeTable.getColumnModel().getColumn(2).setPreferredWidth(10);
		exchangeTable.getColumnModel().getColumn(3).setPreferredWidth(10);
		exchangeTable.getColumnModel().getColumn(4).setPreferredWidth(10);
		exchangeTable.getColumnModel().getColumn(5).setPreferredWidth(40);
		//*/
		
		
		
		mainFrame.getContentPane().add(exchangeTable);
	}
}
